package failover

import (
	"context"
	"errors"
	"gitee.com/yimtune/webook/internal/service/sms"
	"log"
)

type DynamicIndexFailoverSMSService struct {
	svcs []sms.Service
	// 当前服务商下标
	idx int64
}

// 起始下标轮询  不严格的轮询  不是并发安全的
func (f *DynamicIndexFailoverSMSService) Send(ctx context.Context, tplId string, args []string, numbers ...string) error {
	idx := f.idx + 1
	length := int64(len(f.svcs))
	// 我要迭代 length
	for i := idx; i < idx+length; i++ {
		// 从当前idx而非从0开始增长i  会超出length的长度  用取余的办法控制下标在length范围内
		// 取余数来计算下标 对length 取余 相等于限制范围  0 到 length-1
		svc := f.svcs[i%length] // 用i对len取余length
		err := svc.Send(ctx, tplId, args, numbers...)
		switch err {
		case nil:
			return nil
		case context.Canceled, context.DeadlineExceeded: // Canceld 调用者主动取消
			// 前者是被取消，后者是超时
			return err
		}
		log.Println(err)
	}
	return errors.New("轮询了所有的服务商，但是发送都失败了")
}

func NewDynamicIndexFailoverSMSService(svcs []sms.Service) *DynamicIndexFailoverSMSService {
	return &DynamicIndexFailoverSMSService{
		svcs: svcs,
		idx:  -1, // 可以配合测试用例 让可以从下标0 开始测
	}
}
